#import "draw.h"

@implementation GridView
/*
 * This class is the heart of the Grid Inspector modal panel.
 * It implements the draggable grid.  It also provides the external
 * interface (i.e. the runModalForGraphicView: method) to running
 * the panel.  It is a good example of a modal panel.
 * See the Interface Builder file for a better understanding of
 * the outlets and actions sent by controls in the window containing
 * the GridView.
 */

- runModalForGraphicView:(GraphicView *)view
{
    int gridSpacing;
    float gridGray;

    if (graphicView != view) {
	graphicView = view;
	gridSpacing = [view gridSpacing];
	[spacing setIntValue:(gridSpacing >= 4 ? gridSpacing : 10)];
	gridGray = [view gridGray];
	[grayField setFloatValue:gridGray];
	[graySlider setFloatValue:gridGray];
	[self display];
    }

    [NXApp runModalFor:window];
    [window orderOut:self];

    return self;
}

- drawGrid:(int)grid
{
    NXCoord x, y, max, increment;

    increment = (NXCoord)grid;
    max = bounds.origin.y + bounds.size.height;
    for (y = bounds.origin.y; y < max; y += increment) {
	PSmoveto(0.0, y);
	PSlineto(bounds.size.width, y);
    }
    max = bounds.origin.x + bounds.size.width;
    for (x = bounds.origin.x; x < max; x += increment) {
	PSmoveto(x, 0.0);
	PSlineto(x, bounds.size.height);
    }
    PSstroke();

    return self;
}

- drawSelf:(const NXRect *)rects :(int)rectCount
{
    int grid;
    float gray;

    grid = [spacing intValue];
    grid = MAX(grid, 0.0);
    PSsetgray(NX_WHITE);
    NXRectFillList(rects, rectCount);
    if (grid >= 4) {
	gray = [grayField floatValue];
	gray = MIN(gray, 1.0);
	gray = MAX(gray, 0.0);
	PSsetgray(gray);
	PSsetlinewidth(0.0);
	[self drawGrid:grid];
    }
    PSsetgray(NX_BLACK);
    NXFrameRect(&bounds);

    return self;
}

- mouseDown:(NXEvent *)event
{
    NXPoint p, start;
    int grid, gridCount;

    start = event->location;
    [self convertPoint:&start fromView:nil];
    grid = MAX([spacing intValue], 1.0);
    gridCount = (int)MAX(start.x, start.y) / grid;
    gridCount = MAX(gridCount, 1.0);

    [window addToEventMask:NX_MOUSEDRAGGEDMASK|NX_MOUSEUPMASK];

    event = [NXApp getNextEvent:NX_MOUSEDRAGGEDMASK|NX_MOUSEUPMASK];
    while (event->type != NX_MOUSEUP) {
	p = event->location;
	[self convertPoint:&p fromView:nil];
	grid = (int)MAX(p.x, p.y) / gridCount;
	grid = MAX(grid, 1.0);
	if (grid != [spacing intValue]) {
	    [form abortEditing];
	    [spacing setIntValue:grid];
	    [self display];
	}
	event = [NXApp getNextEvent:NX_MOUSEDRAGGEDMASK|NX_MOUSEUPMASK];
    }

    return self;
}

/* Target/Action methods */

- show:sender
{
    [NXApp stopModal];
    [graphicView setGridSpacing:[spacing intValue] andGray:[grayField floatValue]];
    [graphicView setGridVisible:YES];
    return self; 
}

- off:sender
{
    [NXApp stopModal];
    [graphicView setGridSpacing:1];
    return self;
}

- cancel:sender
{
    [NXApp stopModal];
    return self;
}

- changeSpacing:sender
{
    return [self display];
}

- changeGray:sender
{
    if (sender == graySlider) {
	[form abortEditing];
	[grayField setFloatValue:[sender floatValue]];
    } else {
	[graySlider setFloatValue:[sender floatValue]];
    }
    return [self display];
}

/* IB outlet-setting methods */

- setAppIconButton:anObject
{
    [anObject setIcon:"appIcon"];
    return self;
}

@end
